#pragma once
#include "BaseRebot.h"
#include "XTask.h"
#include "XBeHavior.h"
#include "ConfigureRebot.h"
#include "md5.h"

class CSipRobot: public Rebot
{
public:
	CSipRobot(void);
	~CSipRobot(void);
	
};

class UTIL
{
public:
	static void bin2str( unsigned char * s, long l, char * d )
	{
		static char code[] ="0123456789abcdef";
		int i = 0;
		for ( i = 0; i < l; i++ )
		{
			d[2*i  ] = code[(s[i]>>4)&0x0f];
			d[2*i+1] = code[s[i]&0x0f];
		}
		d[2*i] = 0;
	}

	static void str2bin( const char * s, unsigned char * d )
	{
		while ( *s )
		{
			if ( *s <= '9' )
				*d = (*s - '0') << 4;
			else if ( *s <= 'f' )
				*d = (*s - 'a' + 10) << 4;
			else //if ( *s <= 'F' )
				*d = (*s - 'A' + 10) << 4;

			s++;

			if ( *s <= '9' )
				*d += (*s - '0');
			else if ( *s <= 'f' )
				*d += (*s - 'a' + 10);
			else //if ( *s <= 'F' )
				*d += (*s - 'A' + 10);
		
			s++;
			d++;
		}
	}
};
class SipTag
{
public:
	static string CreateCallID()
	{
		string str;
		long long tick = GetNsTick();
		char buff[128]={0};
		sprintf(buff, "%lld",tick);
		str = buff;
		return str;
	};

	static string CreateTagID()
	{
		string str;
		long long tick = GetNsTick();
		char buff[128]={0};
		sprintf(buff, "%lld",tick);
		str = buff;
		return str;
	};

	static string CreateBranchID()
	{
		string str="z9hG4bK";
		long long tick = GetNsTick();
		char buff[128]={0};
		sprintf(buff, "z9hG4bK%lld",tick);
		str = buff;
		return str;
	};

	static string CreateNonce()
	{
		string str;

		return str;
	}

	static int	CheckNonce()
	{

		return 1;
	}

	static string IntToString(int iVal)
	{
		
		char s[32] = {0};
		sprintf_s( s, 31, "%d", iVal );
		return s;
	}

	static string GetAccountName(string& account)
	{
		string str;
		const char* pa = strstr(account.c_str(), "@");
		str = account.substr(0, pa-account.c_str());
		return str;
	}

	static string GetNonceFromHead(string& sHead)
	{
		string str="dbe6af89c8cbc1cee7ed74ae2dd3a33f";
		const char* pNonce= strstr(sHead.c_str(),"nonce=\"");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(sHead.c_str(),"\",opaque");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+7, pEnd-pNonce-7);
		return str;
	}

	static string GetNextNonceFromHead(string& sHead)
	{
		string str="";
		const char* pNonce= strstr(sHead.c_str(),"nextnonce=\"");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(pNonce+12,"\"");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+11, pEnd-pNonce-11);
		return str;
	}

	static string GetTotagFromHead(string& sHead)
	{
		string str;
		const char* pNonce= strstr(sHead.c_str(),"To:");
		const char* pEnd = strstr(pNonce,";tag=");
		if(pNonce == NULL || pEnd == NULL)
			return str;
		pNonce = pEnd;
		pEnd = strstr(pNonce,"\n");
		str = sHead.substr(pNonce-sHead.c_str()+5, pEnd-pNonce-5);
		
		return str;
	}

	static string GetOpaqueFromHead(string& sHead)
	{
		string str="";
		const char* pNonce= strstr(sHead.c_str(),"opaque=\"");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(pNonce+9,"\"");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+8, pEnd-pNonce-8);
		return str;
	}

	static string GetQopFromHead(string& sHead)
	{
		string str="";
		const char* pNonce= strstr(sHead.c_str(),"qop=\"");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(pNonce+6,"\"");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+5, pEnd-pNonce-5);
		return str;
	}

	static string GetAuthenticateFromHead(string& sHead)
	{
		string str="Digest realm=\"TAS_001@pc\",qop=\"auth\",nonce=\"dbe6af89c8cbc1cee7ed74ae2dd3a33f\",opaque=\"248095f4a2a286e3dbb552f3f6597250\"";
		
		const char* pNonce= strstr(sHead.c_str(),"WWW-Authenticate:");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(pNonce,"\n");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+17, pEnd-pNonce-17);
		return str;
	}

	static std::string MD5( std::string s )
	{
		MD5_CTX ctx;
		MD5Init( &ctx );
		MD5Update( &ctx, (unsigned char *)s.c_str(), s.size() );
		unsigned char md5[16];
		MD5Final( md5, &ctx );
		
		char buf[33] = {0};
		UTIL::bin2str( md5, 16, buf );
		return buf;
	}

	static string GetRealmFromHead(string& sHead)
	{
		string str="";
		const char* pNonce= strstr(sHead.c_str(),"realm=\"");
		if(pNonce == NULL)
			return str;
		const char* pEnd = strstr(pNonce+8,"\"");
		if(pEnd == NULL)
			return str;
		str = sHead.substr(pNonce-sHead.c_str()+7, pEnd-pNonce-7);
		return str;
	}

	static string GetResponse()
	{
		string str;

		return str;
	}
};

//=======================================================================================

class ServiceClientRootGroup: public Rebot, public CThread
{
public:

public:
	 char buff[256];
	 int i;
	 bool mIsTrue;

	 ServiceClientRootGroup()
	 {
		 mIsTrue = true;
		 m_pRoot =NULL;
	 }

	 void Close()
	 {
		m_Lock.Lock();
		HttpChannalRobot* pRobot = m_pRoot;
		while(pRobot!=NULL)
		{
			pRobot->Close();
			pRobot = (HttpChannalRobot*)pRobot->pNext;
		}
		m_Lock.UnLock();

		m_pRoot = NULL;
		mIsTrue =false;
		WaitThisThread();
	 }

	virtual unsigned ThreadProc()
	{
		
		while(mIsTrue)
		{
			m_Lock.Lock();
			HttpChannalRobot* pRobot = m_pRoot;
			while(pRobot!=NULL)
			{
				pRobot->UpDataThread();
				pRobot = (HttpChannalRobot*)pRobot->pNext;
			}
			m_Lock.UnLock();
			Sleep(1000);
		}
		return 0;
	}

	bool PushRobot(HttpChannalRobot* pRobot)
	{
		m_Lock.Lock();
		pRobot->pNext = m_pRoot;

		if(m_pRoot!=NULL)
		m_pRoot->pFront = pRobot;

		m_pRoot = pRobot;
		m_Lock.UnLock();
		return true;
	}

	
private:
	CLock			m_Lock;
	HttpChannalRobot*   m_pRoot;
	XTask*				m_pTaskRoot;
};




